package com.tengju.payment.infrastructure.shared.citic;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lsy.baselib.crypto.util.Base64;
import com.tengju.payment.domain.model.channel.CiticChannelInfo;
import com.tengju.payment.infrastructure.external.dto.CiticMerchantBalanceQueryData;
import com.tengju.payment.infrastructure.external.dto.base.BaseCiticTransferData;
import com.tengju.payment.infrastructure.shared.HttpClientUtil;
import com.tengju.payment.infrastructure.shared.InfraException;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import lombok.extern.slf4j.Slf4j;

import java.io.StringWriter;
import java.text.DecimalFormat;

/**
 * 中信代付帮助类
 */
@Slf4j
public class CiticTransferHelper {

    /**
     * 通用发起请求
     *
     * @param citicTransferData 入参
     * @return citicTransferData 出参
     */
    public static BaseCiticTransferData submit(BaseCiticTransferData citicTransferData) {
        XStream xstream = new XStream();
        xstream.autodetectAnnotations(true);
        StringWriter sw = new StringWriter();
        xstream.marshal(citicTransferData, new CompactWriter(sw));
        String requestBody = sw.toString();
        DecimalFormat df = new DecimalFormat("000000");
        String responseXml = doExecute(requestBody, citicTransferData.getMerNo(), citicTransferData.getCiticChannelInfo());
        log.info("[中信-信e汇] - [单笔代付] - [请求参数:{}] - [返回的响应数据：{}]", requestBody, responseXml);
        if (responseXml.contains("<error>")) {
            throw new InfraException("中信代付返回error");
        }

        xstream.processAnnotations(new Class[]{citicTransferData.getClass()});

        ObjectMapper objectMapper = new ObjectMapper();

        return objectMapper.convertValue(xstream.fromXML(responseXml), citicTransferData.getClass());
    }

    public static void main(String[] args) {

        CiticChannelInfo citicChannelInfo = new CiticChannelInfo();
        citicChannelInfo.setMerchantNo("880100020200088");
        citicChannelInfo.setMerchantCer("MIIDKzCCAhOgAwIBAgIBMDANBgkqhkiG9w0BAQUFADAvMQswCQYDVQQGEwJDTjENMAsGA1UECwwEVEVTVDERMA8GA1UEAwwIU2VydmVyIEEwIBcNMjAxMjAxMDMzNTQxWhgPMjEyMDExMDcwMzM1NDJaMC8xCzAJBgNVBAYTAkNOMQ0wCwYDVQQLDARURVNUMREwDwYDVQQDDAhTZXJ2ZXIgQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJHDy97X+bqH4fTnhZAHGYy50TC1rRkTLVFkaysjRtGJF3u8QL+BiN8GjOj836wnSfAfO9J9adj9OUJjCI6/a4EsfswsWoK8ZM53r1zBqR6S5Fy9TKggAZk5/F0bh/hxoLPkXn7l/qmPPsK0eOJvWvv7hJP2ecDEZ5YOv9dJfsPbZrN7HeROOwvIuYOjN7j/Y/4AUbkPbtAo7WhQcCxXPu1h/r12lNh6UFa4w+Iqt8MfZqYvAiESfU3y0pTgrY5p/t9/px/5mfQal+cKVkKVnnVtoLg0FKF76PaUx8H2E1bL7yeUuxl2GDi11ALPuwzItui/hAaed+7dmABE57Pg+q0CAwEAAaNQME4wHQYDVR0OBBYEFPpcKfGfol3veyIBig4T8nc3KWKcMB8GA1UdIwQYMBaAFPpcKfGfol3veyIBig4T8nc3KWKcMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEqSxO+TUOMOLGWcFD7it6xF7bmXPQ/LXxviPiv2XmtwJMrTuN1U9npr/Vg42IpUvuCYTHmzcYnKyu/NZVHA+RrZepZVk+fIfIv6W++4KJW6eBfdboCtwlQ9pimdqR5YZ7NXNiHIPm839fdO6fX4nSa24agglFkuepEMp6xlZGFRVyafY+PFHlEJfPikQsC+6GPCC9DVBDyGAfvlNjUacjDtF5HZgJ6Bl24r/KnCl8WsJoR2AtfF9BxuNs2cU5vE8wXWLZwcbl1iQyTXb4QlOUxnsabdb7ZWqKh52687zFx7sT7DdfHF1/TL6T3pNm+WYYFfvpg3Hhz3WiwI3STu45s=");
        citicChannelInfo.setMerchantKey("A1JTQaNmMqmb5sDvzQ4ZX+U5fYrlqtimiCMoAnb2bHnSwDnYOuPFGv2ZgRdR8MzdZ4g91cn9si1YLG+IFDjxrC55DU2cT0qzrelqaQMlehkFWpfGPRL29T0OQc6604zik3vB7d40bzrjfNOL/FG8roUtFXI85Z7QVpEs0hesUV0EKrqvgCkWZVA4JiSiA8s4UOjsXf0tqBsinZSl6NWalodUN7HxrLwtccFq7wZClCtWqK7p1OBgp9kY24sMQcx61TnNIUjL9LGMZfLem7vFZZJK9yX488pSn9ywHA1YcWubts/hTohSuzqkCLjsj3ceCxKg7mXhVHlcimqKIA7WnBXbEpD2CjxwrSAayT0JT93+6jlcpOZtX448c7p33ZZw+sprfJHqzTH1b/6AlOUrenzrEeAh6ntixexzGDjjXCZNXGNnsiHwbvtnVtp5Dg0qYCmdB8sKCwHaGrRkzPPzgRqFBJC5tnUbXLstw7Ul8pUEFDFvG888sBUn+D52gzU3YDsEJLOXy3fk/TBVG92XNG/qjbprLThXDxU6aRCSMNAchjMaJV7euAYoy+WG4NiL7cDXCnR8TsJbhHVi+N/WY8totCCmrB9b9Y6pQdM2wEkyBTRY677cCLKu5QtumZCv6+AbiWaR2+E8AzSqABkP+/BBvR/CIcRvggjTlLio9/tlYxq65PIUfoVC0HGdhTRvrZKvGn3JpVXEvAPkbzKCN1gI9Au8+ZXthGpXdJg6mGnZAuX6uGH/WEYKobVafN1XpMOvf27DaSMdQytSCy979c4IkwRME2v16XIQrpnyBqCmh+EVv/FkrD2KDs9gk+wz67jEoK/jsygxoo5lm0gOvCS5HkXeD1pXCGo7AZCnIeIRvtAs6DySrEGnoRd7VLobPLguOOtnGpqzAfIJfhAHv0xBHjNm49ZlpoSG0UE5uzfRBkHAHs9ZiJd70bVQgi/W42OuWM0CJAdKW0mioLfcOaJNPhLE5QfEIwRI2ofd9MPPVokh4vOkTttCz75KCXHzvlyLLMKsPFlt9wNN+dYQzuh3wtKC2NmFTYNSBujEGAJhtb+OAkFnZw9wh5Q1uoJgCvDrDz4mJE7fDw+zBRP0456VlUXeNOaGtiHCd4eYA5jYSbgXYyHunqA3CWTFzRW+u8QcsSGaQf9agU7yzOz4OVHgpRL6IXNKRX20HbOlL+Kt1dBzQRkljTeHVmiMmgD/6mmbHUK61icDj1rmRXVtNY673soFIAka5DWeE5Aj6aTsXesTbOqfrjg4QFP3DGE1GRPxfQohLmKm1W8wptkrWMPDmZGPEkvt/DebOe44bbiZCvGRoAny3WL35m50awfP5t03zwP9apvyOZst3Xny+w+N9touyFoksb3k6oj5qKC2mwURf2KPM+GMkist8eGLJneX0GsZc+CNDvsBn0m+t3/Sto6FrVsFYJi0olkxPAJxz/rFWadI0KC3DJJRT5nAuS2n/3aU1UlUiThfnUbhHDxf60j+Ji4hUx72qP6CGR9Ge9sH0z3kQzXT5+G5hrsgGHFifeu9i1a0o8opaS7hv8JjSfG2DvqHS0jhivIckhY1JoMLEl1Ol7K9IvI+yGbaoHyMIK+87N+n8kPvNVmX8pQLreNgf8psL3hQQg==");
        citicChannelInfo.setMerchantPwd("1234223");
        citicChannelInfo.setBankCer("MIIDZTCCAk2gAwIBAgIBMDANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJDTjERMA8GA1UECAwISGFuZ3pob3UxDTALBgNVBAsMBENOQ0IxHDAaBgNVBAMME29scC5iYW5rLmVjaXRpYy5jb20wHhcNMTkwNzMxMDczMTQzWhcNNDYxMjE2MDczMTQzWjBNMQswCQYDVQQGEwJDTjERMA8GA1UECAwISGFuZ3pob3UxDTALBgNVBAsMBENOQ0IxHDAaBgNVBAMME29scC5iYW5rLmVjaXRpYy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCFRQzIjGW8PgULU6TFBSt1z4a33bEKDSzj8Nnl283cmCBVNjApAyjyc5+VCXoOUKmabVlJMbFh6MS0Dg7dQeopHr3TDgoWP3BpTdbNbonsh3a2qP/kVKKHTHIowzI1FOlj35QEc1wq0rzvJSA3qeV96oV1fLE3Sb6sqlPQtKOBNvOMNidF+wbeaSs9n1MtsM83vASWoQzFPaFOsGTRlAKJ0ISZfBK/F0irbBLQjeW27+TQ6BCS1L2imanZngMDylHetYqRAzPX0rkeg8KoIfwttv7DG4FXKZelKZysTAq9TM0q70IoW/kZWdPq7jqHZ8/usLFM8oXeB979zeGeZCjjAgMBAAGjUDBOMB0GA1UdDgQWBBTeZsPiHoe3HBQfkfsQrKnQvvQpoTAfBgNVHSMEGDAWgBTeZsPiHoe3HBQfkfsQrKnQvvQpoTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAAyQeYSXd5VAbdfTsqd1pGit2yxIX2VO4ShDP6taAP/6v+rEbD6GpX6Hj0Qs9DBW6oPxerGhi5x+G5gFQxwxinOPSaMkFaW6fEJDHTltdzsiYA2OfShVT9Qr2W1UbCXbKpW8RH8NrAZjFT6cAUljZAMyminfadc8CF++N3be+v+pXwZMSwA466xtqy3KUagis1CU42X1ReupPk7jpIFnh7Fr8l+Rggeti4FFOHGSPG7QCXyhh6z0HBVtKqTqeCqaKgHofqLeCdpUxpOnoL7C1azyH5x8HdZRGGWMXp0w2VoCNIKcIaCRDgXZqyREK5qAIJvB3+varkEADw5sAFTP7a");
        citicChannelInfo.setBankKey("A1JTQcUu0GVENGrKiwD83xSe8f0rEOhuW+rkCMhir/aQj7vpvjmVGsUO0WulwTJDnBA9b/ckhbZVnGcw9OFikGPcXJCktJsIXCfje6TDi4bFOAFQO/TEEP+JZ10r3jyE4FHaLFTf8/wHUPzNOVSKoGx9CuYnHlM1Bl5028jUBsSlmqWWA/ML7H2nzPItRM+P9e28t85i7zv8AXT5wAcX55NOdTEei4oKge/PH693hw6JFV2+x7YQcTVL0izRnYkT34zYTmkeXw1rLNpnWukAUPUzeaIoS1YqXqas3koDookt+YJoXDmSsofteS7G+oondRfkeoGwOI6P+e8pZSac+RUChaUAUPL66rnkWlSTjrCNdoJmxQhrSdRnT9bpjz5eF9lr3D4RrXaXWvB2Qlj8wXvJ8ZMuqRV5Ap3jEELzGSVs8f+0b9dk9ps0DXn1B7peYUA+0uRMqYfaWADCnpTAGA1JxKViLUfSLTX4sPsQxVfoIMPcVyCC6DQZIF64XNhms9fv9Lw24VdEUI7KMm7Pvb9Fur1mZHFj7IVikoh6N11CLbu692Ji+F4Sy865goDa5WAFIbhghZcRukDbtDxt4f45t27mHL3MhShZidXQUlhlEpRGF4jFJcCXvej9ZgJuEM231qt3E6P7Zfe4lC2sz4Yq3vr2N+WZ0kvHOACTFdhZkfn9SFHYuCoyvxZa75v65p1oHcejCHrq3yuDl/CXAaMFy9d/QGCeBAfY6dP2OPTGIBmnx/qBLvHj2UaqY5K3x0AoOjaTrmzNK7BGunGXSyk+TU8ZPCeVEk6lzv5L2E1l/i0hfIbBxwinkHzUc13WcFs4+3isGFZAzN6Wkfxz1PBp7HthHEFXNr/GGY+90S+vVIpC1tg8vxCBCPzn4niTP2sGfLLp8t+fMWoOqIHWy8ohXqFqTMlkkM2I3hKPGzh9KqzkMKfVYUYKH+UoWStLcWVyUvVB1n55cGsdQ8MNkGpUrVUwyO6ZCMyH9jzBOHW7K2cWWslPfwKGHJVyKcGa2HyiTmK3eQ2sg9aTH1XRnbh9zgiDEPv+m4K19xyW+kvFe9l+nAlYyAtCh5x0Bhy+EQeWaie3FYx5Ta08NB3Qg8CarIGzWYOSXXw/uOS5UuzE5WKBe89aPd3rTmnQfgFyf/WMwng56ULjtuuKxRihfUcUyucKznYjbU4ZwpMBNwNvtMAX8M3w1r3ftZdsa2naZtx+jvoBEnBZVdaTtCLtOlw7S/A5rQxx1J9aHnoN6h6fY+oSdNWW+ZQsDnq8Msn3e2ZLpocNChK7j0k9XMs9I1/2CcXwP51SXZYUfl3XGMyvbvQB5Wae8mvG5Drt8ZTaD+BdENM0r937TbXrmA3DHmq3xkOL00lBmZdI5g/CDmt7aZQyvnRr99AwTFjt/eFI0Sfrh4HEquOBulWi+kG3ur1PGjqiCQQNbyPsNpRiPTiUW4g5C264L00bCC4OaVz2EuyWV223lOU2dMcB2DITOawUDgSI4taI+xFaNNRM8++MAIC8AuZIwRFM+6sFFr4X49koJe6q8s+Ge+AXxZcbLJVfhd6/CWEWu3wjmjDA42KQjKqjMPIIG+ZOnCj4xgVcIRRV8aRnWEbxiLMZZjwOG9uYmwB9K0sOQ/Dng2V+2YuhDPgOlqNM2yIouLM=");
        citicChannelInfo.setBankPwd("5678667");
        citicChannelInfo.setReqChannel("");
        citicChannelInfo.setPlatformTradeCode("T025");
        citicChannelInfo.setSubmitUrl("http://202.108.57.16:30814");

        submit(new CiticMerchantBalanceQueryData(citicChannelInfo));
    }


    //加密帮助类
    private static String doExecute(String requestBody, String merId, CiticChannelInfo citicChannelInfo) {
        String requestHeader = "<?xml version=\"1.0\" encoding=\"GBK\"?>";
        String requestData = requestHeader + requestBody;
        byte[] sessionKey = CiticCrypto.createRandomKey();

        byte[] msgSend = encryptRequestMessageSign(requestData.getBytes(), citicChannelInfo.getMerchantPwd(), citicChannelInfo.getMerchantKey(), citicChannelInfo.getMerchantCer(), citicChannelInfo.getBankCer(), sessionKey);

        byte[] msgResponse = HttpClientUtil.post(citicChannelInfo.getSubmitUrl(), new String(Base64.encode(msgSend)));

        if (msgResponse == null) {
            throw new InfraException("中信银行代付返回信息为空");
        }

        log.info("请求中信银行参数{}，商户号：{}，响应：{}", requestBody, merId, new String(msgResponse));
        return decryptAndValidateMessage(Base64.decode(msgResponse), citicChannelInfo.getBankCer(), citicChannelInfo.getMerchantKey(), citicChannelInfo.getMerchantPwd());
    }


    private static byte[] encryptRequestMessageSign(byte[] plainText, String senderPwd, String senderKey, String senderCer,
                                                    String receiverCer, byte[] sessionKey) {
        String b64StrSign = CiticCrypto.requestMessageSign(plainText, senderPwd, senderKey, senderCer);
        byte[] signStr = ("<signature>" + b64StrSign + "</signature>").getBytes();
        byte[] waitingSignData = CiticCrypto.linkByteArrays(signStr, plainText);
        byte[] cipherText = CiticCrypto.desEdeEncrypt(waitingSignData, sessionKey);
        byte[] sessionCipherText = CiticCrypto.encryptByCerPublicKey(sessionKey, receiverCer);
        return CiticCrypto.linkByteArrays("<sessionkey>".getBytes(), Base64.encode(sessionCipherText), "</sessionkey>".getBytes(), cipherText);
    }


    private static String decryptAndValidateMessage(byte[] cipherResponse, String senderCer, String receiverKey, String receiverPwd) {
        String result = CiticCrypto.decryptResponse(cipherResponse, receiverKey, receiverPwd);
        byte[] decryptData = result.getBytes();
        String sSign = null;
        String openTag2 = "<signature>";
        String closeTag2 = "</signature>";
        byte[] decryptMessage = null;
        int start2 = result.indexOf(openTag2);
        if (start2 != -1) {
            int end2 = result.indexOf(closeTag2, start2 + openTag2.length());
            if (end2 != -1) {
                sSign = result.substring(start2 + openTag2.length(), end2);
                decryptMessage = new byte[decryptData.length - end2 - closeTag2.length()];
                System.arraycopy(decryptData, end2 + closeTag2.length(), decryptMessage, 0, decryptData.length - end2 - closeTag2.length());
            } else {
                log.debug("找不到标签" + closeTag2);
                throw new InfraException("中信代付返回结果校验失败");
            }
        } else {
            log.debug("找不到标签" + openTag2);
            throw new InfraException("中信代付返回结果校验失败");
        }

        boolean checkResult = CiticCrypto.validateRequestMessage(decryptMessage, sSign, senderCer);
        if (!checkResult) {
            throw new InfraException("中信代付返回结果验签失败");
        }

        return new String(decryptMessage);
    }
}
